package com.neo.push.server.connection;

import com.alibaba.fastjson.JSON;
import com.neo.push.core.*;
import com.neo.push.core.connection.AbstractSocketConnection;
import com.neo.push.core.connection.ConnectionListener;
import com.neo.push.server.listener.TimeoutEventListener;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by lock on 17-7-31.
 */
public class PushConnection extends AbstractSocketConnection implements SafetyMessageConnection,TimeoutEventListener {

    private volatile long lastMessageTime;
    private PushMessageHandler messageHandler;
    private TimeUnit unit = TimeUnit.SECONDS;
    private int timeoutSeconds;
    private Logger logger = LoggerFactory.getLogger(PushConnection.class);

    public PushConnection(int timeoutSeconds, ChannelHandlerContext ctx, ConnectionListener listener, PushMessageHandler messageHandler) {
        super(ctx, listener);
        this.timeoutSeconds = timeoutSeconds;
        this.messageHandler = messageHandler;
    }


    @Override
    public void handleMessageTimeout(String messageId) throws Exception {
        close();
        messageHandler.handleMessageTimeout(messageId);
    }

    /**
     * 发送的消息如果不是SafetySocketMessage,则不能够被支持
     * @param message
     */
    @Override
    public void writeMessage(TextMessage message) {
        if(!(message instanceof SafetySocketMessage)){
            logger.error(" not supported message !");
            close();
            return;
        }
        try {
            SafetySocketMessage socketMessage = (SafetySocketMessage) message;
            messageHandler.writeMessage(this, socketMessage);
            this.lastMessageTime = System.currentTimeMillis();
        } catch (Exception e) {
            e.printStackTrace();
            close();
        }
    }

    /**
     * 收到消息，如果收到的是消息回执，则使用SafetyMessageHandler 处理，其他的用处理器处理
     * @param message
     */
    @Override
    public void acceptMessage(TextMessage message) {
        //如果是其他连接，不一定会去处理消息回执
        if((message instanceof Receipt)&&messageHandler.isSupported(message)){
            handleReceipt((Receipt) message);
        }else{
            super.acceptMessage(message);
        }
    }

    /**
     * 连接进行注册，尝试获取离线消息
     * @param registerMessage
     * @throws Exception
     */
    @Override
    public void register(RegisterMessage registerMessage) throws Exception {
        super.register(registerMessage);
        logger.info(" load target offline message");
        List<AcceptPush> pushTextList = messageHandler.loadOfflinePush(registerMessage);
        for(AcceptPush message : pushTextList){
            logger.info(" off line message :"+ JSON.toJSONString(message));
            writeMessage(new SafetyPushText(message));
        }
    }


    @Override
    public void handleReceipt(Receipt receipt) {
        messageHandler.acceptedMessage(this,receipt);
    }

    @Override
    public TimeUnit timeoutUnit() {
        return this.unit;
    }

    @Override
    public int timeout() {
        return this.timeoutSeconds;
    }

    @Override
    public boolean isHoleMessage() {
        //之前没有发送过消息
        if(lastMessageTime==0){
            return true;
        }
        //已发送过消息
        return ((System.currentTimeMillis()-this.lastMessageTime)>this.unit.toMillis(this.timeoutSeconds));
    }
}
